package com.jiahua.utils.string;

import java.text.DateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;

/**
 * 共通バリデーター
 * 
 * @version XXX 1.0
 */
public class CommonValidator {
	/** マッチパターン（ASCII文字のみ） */
	private static final String MATCH_ASCII = "^[\\u0020-\\u007E]+$";
	/** マッチパターン（英字のみ） */
	private static final String MATCH_ALPHA = "^[a-zA-Z]+$";
	/** マッチパターン（ 数字のみ) */
	private static final String MATCH_NUMBER = "^[0-9]+$";
	/** マッチパターン（ひらがなのみ） */
	private static final String MATCH_HIRAGANA = "^[\\u3040-\\u309F]+$";
	/** マッチパターン（カタカナのみ） */
	private static final String MATCH_KATAKANA = "^[\\u30A0-\\u30FF]+$";
	// 半角カタカナのみ
	private static final String MATCH_HANKANA = "^[\\uFF65-\\uFF9F]+$";
	/** 全角文字のみ */
	//private static final String MATCH_ZENKAKU = "^[\\u3040-\\u30FF]+$";
	private static final String MATCH_ZENKAKU = "^[\\u0000-\\u007f\\uff60-\\uff8f]+$";
	/** メールアドレス（簡易：.@や..@はチェックできない） */
	private static final String MATCH_MAIL = "([a-zA-Z0-9][a-zA-Z0-9_.+\\-]*)@(([a-zA-Z0-9][a-zA-Z0-9_\\-]+\\.)+[a-zA-Z]{2,6})";
	/** メールアドレス２（通常） */
	private static final String NOMAL_MATCH_MAIL = "^[_a-zA-Z0-9-\\+]+(\\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9]+)*(\\.[a-zA-Z]{2,6})$";
	/** RFCメールアドレス（RFC準拠。ただし文字数などは別途チェックする） */
	private static final String RFC_MATCH_MAIL = "^((([a-z]|[A-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z]|[A-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|[A-Z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[A-Z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|[A-Z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[A-Z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[A-Z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[A-Z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|[A-Z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[A-Z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))$";

	/** URL */
	private static final String MATCH_URL = "^(https?|ftp)(:\\/\\/[-_.!~*\\'()a-zA-Z0-9;\\/?:\\@&=+\\$,%#]+)$";

	/** 検索文字列 */
	private static final String MATCH_NG_CHARACTER = ".*[　,%_*=/\\+\\-&$!\\\\(\\\\\\\\)@\\[\\]{\\'}<>].*";

	/*
	 * ・以下、禁則文字をチェック "　", ",", "%", "_", "*", "=", "/", "+", "-", "&", "$", "!",
	 * "\"", "\\", "'", "(", ")", "@", "[", "]", "{", "}", "<", ">" ・40byteまで
	 */

	/**
	 * コンストラクタ
	 */
	private CommonValidator() {
	}

	/**
	 * 検索禁止文字？
	 * 
	 * @param strField
	 * @return boolean
	 */
	public static boolean isNgWord(String strField) {
		if (strField.matches(MATCH_NG_CHARACTER)) {
			return true;
		}
		return false;
	}

	/**
	 * null check
	 * 
	 * @param strField
	 *            文字列
	 * @return True(nullか空文字)/False(それ以外)
	 */
	public static boolean isNull(String strField) {
		if (strField == null || strField.equals("")) {
			return true;
		}
		return false;
	}

	/**
	 * @param strField
	 * @return boolean
	 */
	public static boolean isNotNull(String strField) {
		if (strField == null || strField.equals("")) {
			return false;
		}
		return true;
	}

	/**
	 * nullの置き換え
	 * 
	 * @param strField
	 *            文字列
	 * @return 文字列
	 */
	public static String chgNull(String strField) {
		StringBuffer sbfField2 = new StringBuffer();
		if (strField == null) {
			sbfField2.append("");
		} else {
			sbfField2.append(strField);
		}
		return sbfField2.toString();
	}

	/**
	 * ASCII文字のみかチェック
	 * 
	 * @param strField
	 *            ASCII文字
	 * @return True(正常)/False(異常)
	 */
	public static boolean isAscii(String strField) {
		if (strField.matches(MATCH_ASCII)) {
			return true;
		}
		return false;
	}

	/**
	 * 英字のみかチェック
	 * 
	 * @param strField
	 *            英字
	 * @return True(正常)/False(異常)
	 */
	public static boolean isAlpha(String strField) {
		if (strField.matches(MATCH_ALPHA)) {
			return true;
		}
		return false;
	}

	/**
	 * 数字のみかチェック
	 * 
	 * @param strField
	 *            数字
	 * @return True(正常)/False(異常)
	 */
	public static boolean isNumber(String strField) {
		if (strField.matches(MATCH_NUMBER)) {
			return true;
		}
		return false;
	}

	/**
	 * ひらがなのみかチェック
	 * 
	 * @param strField
	 *            ひらがな
	 * @return True(正常)/False(異常)
	 */
	public static boolean isHiragana(String strField) {
		if (strField.matches(MATCH_HIRAGANA)) {
			return true;
		}
		return false;
	}

	/**
	 * カタカナのみかチェック
	 * 
	 * @param strField
	 *            カタカナ
	 * @return True(正常)/False(異常)
	 */
	public static boolean isKatakana(String strField) {
		if (strField.matches(MATCH_KATAKANA)) {
			return true;
		}
		return false;
	}

	/**
	 * 半カタカナのみかチェック
	 * 
	 * @param strField
	 *            半カタカナ
	 * @return True(正常)/False(異常)
	 */
	public static boolean isHankana(String strField) {
		if (strField.matches(MATCH_HANKANA)) {
			return true;
		}
		return false;
	}

	/**
	 * 全角文字のみかチェック
	 * 
	 * @param strField
	 *            全角文字
	 * @return True(正常)/False(異常)
	 */
	public static boolean isZenkaku(String strField) {
		if (strField.matches(MATCH_ZENKAKU)) {
			return true;
		}
		return false;
	}

	/**
	 * メールアドレス（簡易）かチェック
	 * 
	 * @param strField
	 *            メールアドレス
	 * @return True(正常)/False(異常)
	 */
	public static boolean isMail(String strField) {
		if (strField.matches(MATCH_MAIL)) {
			return true;
		}
		return false;
	}

	/**
	 * ＵＲＬかチェック
	 * 
	 * @param strField
	 *            URL
	 * @return True(正常)/False(異常)
	 */
	public static boolean isUrl(String strField) {
		if (!strField.matches(MATCH_URL)) {
			return false;
		}
		return true;
	}

	/**
	 * 日付のチェック
	 * 
	 * @param strDate
	 *            日付
	 * @return True(正常)/False(異常)
	 */
	public static boolean isDate(String strDate) {
		boolean check = true;

		if (strDate == null || strDate.length() != 10) {
			check = false;
		}

		strDate = strDate.replace('-', '/');
		DateFormat format = DateFormat.getDateInstance();

		// 日付/時刻解析を厳密に行うかどうかを設定する。
		format.setLenient(false);
		if (check == true) {
			try {
				format.parse(strDate);
				check = true;
			} catch (Exception e) {
				check = false;
			}
		}

		return check;
	}

	/**
	 * 文字のバイトサイズ取得
	 * 
	 * @param strField
	 *            文字列
	 * @return バイト数
	 */
	public static int getByteSize(String strField) {
		return (CommonValidator.isNull(strField) ? 0 : strField.getBytes().length);
	}

	/**
	 * 文字数　取得
	 * 
	 * @param strField
	 *            文字列
	 * @return 文字数
	 */
	public static int getSize(String strField) {
		return (CommonValidator.isNull(strField) ? 0 : strField.length());
	}

	/**
	 * 最大文字数チェック
	 * 
	 * @param strField
	 *            文字列
	 * @param strNum
	 *            入力可能最大文字数
	 * @return true:入力可能最大文字数以内,false:入力可能最大文字数より大きい
	 */
	public static boolean isMaxLength(String strField, int maxLength) {
		return (CommonValidator.getSize(strField) > maxLength) ? false : true;
	}

	/**
	 * 最小文字数チェック
	 * 
	 * @param strField
	 *            文字列
	 * @param strNum
	 *            入力可能最小文字数
	 * @return true:入力可能最小文字数以上,false:入力可能最小文字数より小さい
	 */
	public static boolean isMinLength(String strField, int minLength) {
		return (CommonValidator.getSize(strField) < minLength) ? false : true;
	}

	/**
	 * 日付 チェック
	 * 
	 * @param yyy
	 *            mm dd year month day 文字列
	 * @return True(正常)/False(異常)
	 */
	public static boolean isExistsDate(String yyyy, String mm, String dd) {

		try {
			int year = Integer.parseInt(yyyy);
			int month = Integer.parseInt(mm);
			int day = Integer.parseInt(dd);
			return isExistsDate(year, month, day);
		} catch (NumberFormatException e) {
			return false;
		}
	}

	public static boolean isExistsDate(int year, int month, int day) {

		Calendar gc = new GregorianCalendar(year, month - 1, day);

		if (gc.get(Calendar.YEAR) != year || gc.get(Calendar.MONTH) != (month - 1)
				|| gc.get(Calendar.DAY_OF_MONTH) != day) {
			return false;
		} else {
			return true;
		}
	}

	/**
	 * メールアドレス（RFC)形式チェック. 文字数などは別途チェックする.
	 * 
	 * @param strField
	 *            メールアドレス
	 * @return True(正常)/False(異常)
	 */
	public static boolean isRfcMail(String strField) {
		// -から始まる場合を除外
		final String MINUS = "\\-.*";
		if (strField.matches(MINUS)) {
			return false;
		}

		if (strField.matches(RFC_MATCH_MAIL)) {
			return true;
		}
		return false;
	}
	
    public static void main(String args[]) {
    	
    	System.out.println(isZenkaku("会社名"));
    }

}